/**
 * 
 */
package com.ideeli.webextractor.service;

import static com.ideeli.webextractor.utils.Constants.*;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;

import com.ideeli.hwz.domain.HWZProduct;
import com.ideeli.webextractor.dao.ProductDao;
import com.ideeli.webextractor.domain.Category;
import com.ideeli.webextractor.domain.Manufacturer;
import com.ideeli.webextractor.domain.Product;
import com.ideeli.webextractor.domain.ProductDetail;
import com.ideeli.webextractor.utils.Utility;


/**
 * @author sa
 *
 */
public class ProductServiceImpl implements ProductService
{
	private static final Logger logger = Logger.getLogger(ProductServiceImpl.class);
	
	private ProductDao productDao;
	private CacheService cacheService;
	
	private PriceChangeService priceChangeService;
	
	private Map<String,Integer> allSkuVpnsPidMap;
	private Map<String,Integer> parsedSkuVpnsInstance;



	/* (non-Javadoc)
	 * @see com.ideeli.webextractor.service.ProductService#insertNewProduct(com.ideeli.webextractor.domain.ProductDetail)
	 */
	@Override
	public void insertINGProduct(ProductDetail productDetail) throws Exception
	{
		logger.warn("insertProductinDB..");
		Product product=mapProdDetailtoProduct(productDetail);
		productDao.insertProduct(product);
		productDetail.setProductId(product.getProduct_id());
		assignCategory(productDetail.getCategory(),productDetail.getSubCategory(),product);

	}
	
	public void insertSISProduct(String model, String sku, String upc, String brand,
			String basePrice,String stnRetailPrice,String image, String name, String meta,
			String supplier, String prodDesc, String subCat, String topCat) throws Exception
	{
		lazyLoad(SIS_ID);
	

		
		Product product= new Product();
		product.setModel(model);
		product.setSku(sku);
		product.setUpc(upc);
		String skuUpcModel=sku+upc+model;

		
		product.setLocation("Singapore");
		product.setStock_status_id(7);
		
		//vendor must be set before the call to mapPrice
		product.setVendor(brand);
		product.setManufacturer_id(mapNinsertManufacturer(brand));
		product.setShipping((short)1);
		
		product.setQuantity(mapQuantity(product.getPrice()));
		
		//supplier must be mapped before the map price
		product.setSupplierId(mapSupplier(supplier));
		
		//stnRetail must be set before the call to mapPrice
		float stnRetailP=Float.parseFloat(stnRetailPrice);
		product.setStnRetailPrice(Utility.round2(stnRetailP));
		
		
		
		//if this is already parsed check if price update required
		if (allSkuVpnsPidMap.containsKey(skuUpcModel))
		{
			//price update required if not parsed in last 24 hours
			if(!parsedSkuVpnsInstance.containsKey(skuUpcModel))
			{
				//Update the price
				Integer prodId=allSkuVpnsPidMap.get(skuUpcModel);
				priceChangeService.updatePrice(Float.parseFloat(basePrice), prodId);
//				productDao.updatePrice(prodId, product.getPrice(), product.getProfit_percent(),product.getBase_price());
//				cacheService.addUpdateProdPriceList(prodId+"", "Old:"+product.getBase_price()+"-->new Price:"+product.getPrice());
				markAsProductParsed(sku, upc, model, name, prodId);
				parsedSkuVpnsInstance.put(skuUpcModel, prodId);
				
			}
			
			return;
		}
		
		try
		{
			priceChangeService.mapPrice(basePrice,product);
		}
		catch(NumberFormatException e)
		{
			cacheService.addErrorToList(e.getMessage()+sku+upc);
			logger.error(e);
			
		}
		
		
		//This flag must be checked after the skipProduct flag.
		if(product.isSkipProduct())
			return;
		
		
		product.setImage(image);
		product.setLargeImage(image);
		product.setQuantity(3);
		product.setPoints(0);
		
		product.setTax_class_id(9);
		
		product.setDate_available(Utility.getCurrentTS());
		product.setWeight(0f);
		product.setWeight_class_id(1);
		product.setLength(0f);
		product.setHeight(0f);
		product.setWidth(0f);
		product.setLength_class_id(3);
		product.setSubtract((short)1);
		product.setMinimum(1);
		//TODO default short order higher means lower in the view 
		product.setSort_order(8);
		product.setStatus((short)1);
		product.setDate_added(Utility.getCurrentTS());
		product.setDate_modified(Utility.getCurrentTS());
		product.setViewed(0);
		
		
		product.setLanguage_id(1);
		product.setName(Utility.getProductName(name));
		
		if(meta!=null && meta.length()>253)
			meta=meta.substring(0, 253);
		
		product.setMeta_description(meta);
		product.setMeta_keyword(meta);

		
		
		product.setDescription(prodDesc);
		
		productDao.insertProduct(product);
		
		assignCategory(topCat,subCat , product);
		
		
		//product marking logics
		allSkuVpnsPidMap.put(skuUpcModel, product.getProduct_id());
		parsedSkuVpnsInstance.put(skuUpcModel, product.getProduct_id());
		markAsProductParsed(sku, upc, model, name, product.getProduct_id());
		
	}
	
	@Override
	public void markAsProductParsed(String sku, String vpn, String model, String name, int prodId) throws Exception
	{
		logger.warn("markAsProductParsed.."+sku);
		productDao.insertParsedProduct(sku, vpn,model, name, prodId);
	}

	public void assignCategory(String topCategoryName,String subCategoryName,   Product product) throws Exception
	{
		logger.info("insertCategory..");
//		String topCategoryName = productDetail.getCategory();
//		String subCategoryName = productDetail.getSubCategory();
		//TODO 
//		String productType = productDetail.getProductType();
		
		
		int parentCatId=insertCategoryNcreateCatCache(topCategoryName, TOP_CAT);
		int subCatId=insertCategoryNcreateCatCache(subCategoryName, parentCatId);
		
		if(subCatId>0)
		{
			productDao.insertProdToCat(product.getProduct_id(), subCatId);
		}
		else
		{
			productDao.insertProdToCat(product.getProduct_id(), parentCatId);
		}
		
	}

	private int insertCategoryNcreateCatCache(String categoryName,int topOrParent) throws Exception
	{
		logger.info("get cat id from cache..");
		int categoryId=cacheService.getCategoryId(categoryName);
		
		if(categoryId==-1)
		{
			logger.info("not found in cache.. try to get from db..");
			categoryId=productDao.findCategoryIdByName(categoryName);
			cacheService.addCacheCatId(categoryName, categoryId);
		}
		
		Category category=null;
		
		if(categoryId==-1)
		{
			logger.info("not found in db..create a new one");
			category=mapCategory(categoryName,topOrParent);
			productDao.insertCategory(category);
			categoryId=category.getCategory_id();
			cacheService.addCacheCatId(categoryName, categoryId);
		}
		
		return categoryId;
	}
	
	private Category mapCategory(String name,int top)
	{
		logger.info("mapCategory()");
		Category category = new Category();
		category.setName(name);
		category.setDate_added(Utility.getCurrentTS());
		category.setDate_modified(Utility.getCurrentTS());
		category.setDescription(name);
		category.setLanguage_id(1);
		category.setMeta_description(name);
		category.setStatus((short)1);
		if(top==TOP_CAT)
		{
			//TODO set top categories by sql
//			category.setTop((short)1);
		}
		else
		{
			category.setParent_id(top);
		}
		
//		TODO category.setImage("")
		category.setMeta_keyword(name);
		
		return category;
		
	}

	private Product mapProdDetailtoProduct(ProductDetail productDetail) throws Exception
	{
		logger.info("mapProdDetailtoProduct()");
		
		Product product = new Product();
//		product.setProduct_id(" ");//get max at db level
		product.setModel(mapProductModel(productDetail));
		product.setSku(productDetail.getSku());
		product.setUpc(productDetail.getVpn());
		product.setLocation("Singapore");
		product.setStock_status_id(7);
		
		product.setVendor(productDetail.getVendor());
		product.setManufacturer_id(mapNinsertManufacturer(productDetail.getVendor()));
		product.setShipping((short)1);
		
		String priceStr=productDetail.getYourPrice();
		priceChangeService.mapPrice(priceStr,product);


		product.setImage(productDetail.getSmallImage());
		product.setLargeImage(productDetail.getLargeImage());

		
//		product.setBase_price(Utility.productDetail.getYourPrice());
//		product.setPrice(mapPrice(productDetail));
		//following must be called after price set
		product.setQuantity(mapQuantity(product.getPrice()));
		product.setPoints(0);
		//TODO confirm following tax class id
		product.setTax_class_id(9);
		
		product.setDate_available(Utility.getCurrentTS());
		product.setWeight(0f);
		product.setWeight_class_id(1);
		product.setLength(0f);
		product.setHeight(0f);
		product.setWidth(0f);
		product.setLength_class_id(3);
		product.setSubtract((short)1);
		product.setMinimum(1);
		//TODO default short order higher means lower in the view 
		product.setSort_order(8);
		product.setStatus((short)1);
		product.setDate_added(Utility.getCurrentTS());
		product.setDate_modified(Utility.getCurrentTS());
		product.setViewed(0);
		
		product.setLanguage_id(1);
		String productName=Utility.getProductName(productDetail.getProductName());

			product.setName(productName);
		
//		product.setDescription(productDetail.getExtendedSpec());
		product.setDescription(productDetail.getProductName()+"</br></br><b>Basic specification:</b></br>"+productDetail.getBasicSpecHtml()+
				"</br></br> <b>Detail specification:</b></br></br>"+productDetail.getExtendedSpecHtml());
		
		String meta=getProductMeta(productDetail);
		
		if(meta!=null && meta.length()>253)
			meta=meta.substring(0, 253);
		
		product.setMeta_description(meta);
		product.setMeta_keyword(meta);
		
		
		product.setSupplierId(mapSupplier(productDetail.getSupplier()));
		
		return product;		
	}
	

	private String getProductMeta(ProductDetail productDetail)
	{
		StringBuilder str= new StringBuilder();
		str.append(productDetail.getProductName()).append(",");
		str.append(productDetail.getProductType()).append(",");
		str.append(productDetail.getVendor()).append(",");
		str.append(productDetail.getSku()).append(",");
		str.append(productDetail.getVpn()).append(",");
		str.append(productDetail.getCategory()).append(",");
		
		if(str.length()>2040)
		{
			return str.substring(0, 2040);
		}
		
		return str.toString();
	}

	public int mapSupplier(String sname) throws Exception{
		
		sname=sname.trim();
		
		int supId=cacheService.getSupplierId(sname);
		
		if(supId==-1)
		{
			supId=productDao.findSupplierByName(sname);
			cacheService.addSupplierNameId(sname, supId);
		}
		
		
		if(supId==-1)
		{
			supId=productDao.insertSupplier(sname);
			cacheService.addSupplierNameId(sname, supId);
		}
		
		return supId;
		
		
	}

	private String mapProductModel(ProductDetail productDetail) {
		
		String model=productDetail.getExtPropMap().get("Product Model");
		
		if(!Utility.isNull(model))
		{
			return model;
		}
		
		model=productDetail.getVpn();
		
		if(!Utility.isNull(model))
		{
			return model;
		}

		
		model=productDetail.getExtPropMap().get("Product Name");
		
		if(!Utility.isNull(model))
		{
			return model;
		}
		
		return "-";
	}


	private int mapQuantity(float price)
	{
		logger.info("mapQuantity()");
		
		if(price < 10 )
		{
			return 20;
		}
		else if(price < 50 )
		{
			return 15;
		}
		else if(price < 100 )
		{
			return 10;
		}
		else if(price < 200 )
		{
			return 8;
		}
		else if(price < 500 )
		{
			return 6;
		}
		else if(price < 2000 )
		{
			return 4;
		}
		else if(price < 5000 )
		{
			return 3;
		}
		
		return 2;
	}
	


	
	private float getShippingFee(float basePrice)
	{
		if(basePrice>=100)
		{
			return 5f;
		}
 
		return 0;
	}

	private float getProfitPercent(float basePrice)
	{
		if(basePrice<100)
		{
			return 7.75f;
		}
		
		return 5.5f;
	}

	public int mapNinsertManufacturer(String name) throws Exception
	{
		logger.warn("mapNinsertManufacturer()");
		
		int manId=cacheService.getManufacturerFrmCache(name);
		
		if(manId==-1)
		{
			manId=productDao.findManufacturerByName(name);
			cacheService.addManufacturerCache(name, manId);
		}
		
		
		if(manId==-1)
		{
			Manufacturer manufacturer = new Manufacturer();
			manufacturer.setName(name);
			
			String manImage="data/images/brands/"+name+".jpg";
			manufacturer.setImage(manImage);
			manufacturer.setName(name);
			manufacturer.setSort_order((short)0);
			
			manufacturer.setBannerId(8);
			manufacturer.setBannerImage(manImage);
			manufacturer.setTitle(name);
			
			
			productDao.insertManufacturer(manufacturer);
			manId=manufacturer.getManufacturer_id();
			cacheService.addManufacturerCache(name, manId);
		}
		
		return manId;
	} 

	public  void deleteUnlisted(int supplierid) throws Exception {
		
		Map<String,Integer> allSkuVpnsPidMap=cacheService.getAllSkuVpns(supplierid);
		Map<String,Integer> parsedSkuVpns=cacheService.getParsedSkuVpns(supplierid);
		List<Integer> deleteProducts= new ArrayList<Integer>();
		
		List<Product> products=productDao.findAllOrderedProducts();
		List<Integer> orderdPs=new ArrayList<Integer>();
		List<Integer> orderdOutOfStks=new ArrayList<Integer>();
		
		for(Product p: products)
			orderdPs.add(p.getProduct_id());
		
		
		for(String skuVpn: allSkuVpnsPidMap.keySet())
		{
			if(!parsedSkuVpns.containsKey(skuVpn))
			{
				int delProdId=allSkuVpnsPidMap.get(skuVpn);
				if(orderdPs.contains(delProdId))
				{
					logger.warn("in Ordered list prod id:"+delProdId);
					orderdOutOfStks.add(delProdId);
				}
				else
				{
					
					deleteProducts.add(delProdId);
				}
			}
			
		}
		
		productDao.markInactiveOutofStock(orderdOutOfStks);
		logger.warn("not in ordered list deleting"+deleteProducts);
		
		int delLimit=Integer.parseInt(cacheService.getAppProperty(DEL_LIMIT));
		
		if(deleteProducts.size()<delLimit)
			productDao.deleteProduct(deleteProducts);
		else
			logger.warn("***************Product delete is on hold, check the logic as they are more than !!!!!!!!!!!!!  "+delLimit);
		
	}
	


	/* (non-Javadoc)
	 * @see com.ideeli.webextractor.service.IngExtractorService#extract()
	 */
	
	public ProductDao getProductDao() {
		return productDao;
	}


	public void setProductDao(ProductDao productDao) {
		this.productDao = productDao;
	}

	public CacheService getCacheService()
	{
		return cacheService;
	}

	public void setCacheService(CacheService cacheService)
	{
		this.cacheService = cacheService;
	}
	
	private void lazyLoad(int sid)
	{
		if(allSkuVpnsPidMap==null)
			allSkuVpnsPidMap=cacheService.getAllSkuVpns(sid);
		
		if(parsedSkuVpnsInstance==null)
			parsedSkuVpnsInstance=cacheService.getParsedSkuVpns(sid);

	}

	public PriceChangeService getPriceChangeService() {
		return priceChangeService;
	}

	public void setPriceChangeService(PriceChangeService priceChangeService) {
		this.priceChangeService = priceChangeService;
	}
	
	public void createFeaturedProdcuts() throws Exception
	{
		
		logger.warn("Start getProductUploadList");
		List<String> prodsToUpload=new ArrayList<String>();

		Map<String, List<String>> catProds=productDao.getCategoryProdsForFeaturedList();

		int featuredCount=12;
		int counter=0;
		
		for(String cat: catProds.keySet())
		{
			logger.info("cat:"+cat);
			String prefferedCat="440,400,222,419,445,402,403,468,439,415,251";
			if(prefferedCat.contains(cat))
			{
				for(String prod:catProds.get(cat))
				{
					counter++;
					prodsToUpload.add(prod);
					break;
				}
				if(counter>=featuredCount)
					break;

			}
		}
		
		if(counter<featuredCount)
		{
			for(String cat: catProds.keySet())
			{
				logger.info("cat:"+cat);
				String prefferedCat="440,400,222,419,445,402,403,468,439,415,251";
				if(!prefferedCat.contains(cat))
				{
					for(String prod:catProds.get(cat))
					{
						counter++;
						prodsToUpload.add(prod);
						break;
					}
					if(counter>=featuredCount)
						break;

				}
			}
		}
	
		
		logger.info("prodIDs to add to featrued list:"+prodsToUpload);
		StringBuilder prods=new StringBuilder();
		for(String str: prodsToUpload)
		{
			prods.append(str).append(",");
		}
		prods.deleteCharAt(prods.lastIndexOf(","));
		productDao.updateFeaturedProdList(prods.toString());
	}



}
